package com.innovation.wjrpc.result;

import com.innovation.wjrpc.protocol.Response;
import com.innovation.wjrpc.protocol.StatusCheck;
import com.innovation.wjrpc.status.AsyncResponseStatus;
import lombok.extern.slf4j.Slf4j;

import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.LockSupport;

/**
 * @author innoyiya
 * @date 2021/9/10 9:52
 */
@Slf4j
public class ResultsMap {

    private static ConcurrentHashMap<Long, AsyncResponse> concurrentHashMap;

    static {
        concurrentHashMap = new ConcurrentHashMap();
    }


    //同步获取响应结果
    public static Response getResponseById(Long id) {
        AsyncResponse asyncResponse = concurrentHashMap.get(id);

        if (asyncResponse.getStatus().equals(AsyncResponseStatus.SENT) || asyncResponse.getStatus().equals(AsyncResponseStatus.IN_HAND)) {
//            log.info("park id = {} in {} ", id, System.nanoTime());
            //LockSupport.park();
            // TODO: 2021/9/14 挂起操作需要优化
            LockSupport.parkNanos(500000);
            while (!asyncResponse.getStatus().equals(AsyncResponseStatus.RECEIVE)){}
//            log.warn("[{}] get status is {}", Thread.currentThread().getName(), asyncResponse.getStatus());
        }

        if ((asyncResponse = concurrentHashMap.get(id)).getStatus().equals(AsyncResponseStatus.RECEIVE)) {
            concurrentHashMap.remove(id);
            //LockSupport.parkNanos(1);
            return asyncResponse.getResponse();
        }
        log.warn("return status of response of id = {} is {} ", id, asyncResponse.getStatus());
        return asyncResponse.getResponse();
//        while (!(asyncResponse = concurrentHashMap.get(id)).getStatus().equals(AsyncResponseStatus.RECEIVE))
//        asyncResponse.setStatus(AsyncResponseStatus.REMOVED);
//        log.warn("return status of response of id = {} is {} ", id, asyncResponse.getStatus());
//        return asyncResponse.getResponse();


    }

    public static Long GenerateId() {
        return Math.abs(UUID.randomUUID().getLeastSignificantBits());
    }

    //将任务放入表中
    public static Long setResponseById(Long id){
        AsyncResponse asyncResponse = new AsyncResponse();
        asyncResponse.setStatus(AsyncResponseStatus.SENT);
        asyncResponse.setThread(Thread.currentThread());
        concurrentHashMap.put(id, asyncResponse);
        return id;
    }

    //更新结果并唤醒等待线程
    public static void updateResult(Long id, Response response) {
        if (StatusCheck.isTreated(response)) {
            AsyncResponse asyncResponse = concurrentHashMap.get(id);
            asyncResponse.setResponse(response);
            asyncResponse.setStatus(AsyncResponseStatus.RECEIVE);
            LockSupport.unpark(asyncResponse.getThread());
//            log.info("unPark id = {}  in {} and code = {} and thread is {}", response.getId(), System.nanoTime(), response.getCode(), asyncResponse.getThread().getName());
        }else if (StatusCheck.isInHand(response)) {

        }else {
            updateResponse(response.getId(), AsyncResponseStatus.IN_HAND);
        }


    }
    public static void updateResponse(Long id, AsyncResponseStatus status){
        try {
            concurrentHashMap.get(id).setStatus(status);
        }catch (NullPointerException e) {
            log.warn(Thread.currentThread().getName() +  " Exception id is " + id);
            e.printStackTrace();
        }
    }
}
